from celery import shared_task

from lib.common import CacheKeys
from services.datamodel.vip.models import (mm_UserCards, UserCards, mm_UserCardLogs)
from django.db import transaction
from apps.student.share import app_logger
from django.utils import timezone
from datetime import datetime
import json
from django.core.cache import cache
from django.db.models import Sum
from project.settings import USER_LEVEL
from django.db.models import Q
import traceback
from services.datamodel.history.models import (mm_HistoryCache)


@shared_task(ignore_result=True)
def send_cards(buyer_id, nums, expired_at, seller_id, channel, level=None, seller_level=None,
               role_id=None, admin_id=None):
    if buyer_id == seller_id:
        return {'retcode': 1, "msg": "无法给自己派卡！"}
    if buyer_id is None:
        return {'retcode': 1, "msg": "购买用户id为空！"}
    if role_id is None:
        return {'retcode': 1, "msg": "请选择卡类型！"}
    # wni：校验 1. 被开卡用户是他的下级，没有则提示先开户
    if not level:
        return {'retcode': 1, "msg": "请先开户！"}

    # 除了超管和运营人员， 需要判断只能上级给下级判断
    if (seller_level in [USER_LEVEL.LEVEL_SHENG, USER_LEVEL.LEVEL_SHI, USER_LEVEL.LEVEL_QU,
                         USER_LEVEL.LEVEL_ENDORSEMENT, USER_LEVEL.LEVEL_OPERATOR, USER_LEVEL.LEVEL_PLATINUM]) \
            and seller_level > level:
        return {'retcode': 1, 'msg': "只能给下级派卡！"}

    # 显式的开启一个事务
    with transaction.atomic():
        # 创建事务保存点
        save_id = transaction.savepoint()
        # 暴力回滚
        try:
            expiredat = ''
            if seller_id == 1:
                cards = UserCards.objects.select_for_update().filter(
                    student_id=seller_id, status=0, role_id=role_id).order_by('id')[:int(nums)]
                expiredat = expired_at
                # wni: 系统创建的卡没有过期时间，派出去才有
            else:
                cards = UserCards.objects.select_for_update().\
                        filter(student_id=seller_id, status=0, expired_at__gte=timezone.now(), role_id=role_id).\
                        order_by('expired_at')[:int(nums)]
            if cards.count() < int(nums):
                return {'retcode': 1, "msg": "余卡不足！"}
            card_list = [i.id for i in cards]
            if seller_id == 1:
                UserCards.objects.filter(id__in=card_list).update(
                    student_id=buyer_id, channel=channel, expired_at=expired_at)
            else:
                UserCards.objects.filter(id__in=card_list).update(student_id=buyer_id, channel=channel)
                expiredat = cards[0].expired_at
            mm_UserCardLogs.create(
                seller_student_id=seller_id,
                cards=json.dumps(card_list),
                buyer_student_id=buyer_id,
                nums=int(nums),
                day=timezone.now().strftime("%Y-%m-%d"),
                channel=channel,
                expired_at=expiredat,
                admin_id=admin_id,
                role_id=role_id
            )
            # 记录缓存
            # seller_key = CacheKeys.USER_BALANCE % (str(seller_id), str(role_id))
            # buyer_key = CacheKeys.USER_BALANCE % (str(buyer_id), str(role_id))
            user_total = CacheKeys.USER_TOTAL_CARD % (str(buyer_id), str(role_id))
            # user_cards_num_buyer = cache.get(buyer_key)
            # if user_cards_num_buyer:
            #     cache.incr(buyer_key, int(nums))  # 买卡用户递增
            # else:
            #     # 从数据库获取
            #     buyer_sum = UserCards.objects.filter(Q(expired_at__isnull=True) | Q(expired_at__gt=datetime.now()),
            #                                          status=0, student_id=buyer_id, role_id=role_id).count()
            #     cache.set(buyer_key, buyer_sum, None)
            # user_cards_num_seller = cache.get(seller_key)
            # if user_cards_num_seller:
            #     cache.decr(seller_key, int(nums))  # 卖卡递减
            # else:
            #     seller_sum = UserCards.objects.filter(Q(expired_at__isnull=True) | Q(expired_at__gt=datetime.now()),
            #                                           status=0, student_id=seller_id, role_id=role_id).count()
            #     cache.set(seller_key, seller_sum, None)
            cards_total_user = cache.get(user_total)
            if cards_total_user:
                cache.incr(user_total, int(nums))  # 总卡数--系统至今累计的买卡数量
                mm_HistoryCache.add_data(name="用户累计购卡总数", day=timezone.now().strftime("%Y-%m-%d"),
                                         cache_key=user_total, cache_value=cache.get(user_total))

            else:
                from services.datamodel.student.models import mm_StudentTeam
                userObj = mm_StudentTeam.get_or_default(student_id=buyer_id, status=2)
                if userObj:
                    total = mm_UserCardLogs.filter(buyer_student_id=buyer_id, role_id=role_id, channel__in=[2, 6],
                                                   created_at__gte=userObj.created_at).aggregate(sum=Sum("nums"))
                else:
                    total = mm_UserCardLogs.filter(buyer_student_id=buyer_id, role_id=role_id, channel__in=[2, 6]).\
                        aggregate(sum=Sum("nums"))
                cache.set(user_total, total['sum'], None)  # wni: 只用统计买家
                mm_HistoryCache.add_data(name="用户累计购卡总数", day=timezone.now().strftime("%Y-%m-%d"),
                                         cache_key=user_total, cache_value=total['sum'])
        except Exception as e:
            err = traceback.format_exc()
            app_logger.error(err)
            transaction.savepoint_rollback(save_id)  # 回滚
            return {'retcode': 1, "msg": "发卡异常！"}
            # 提交成功，显式的提交一次事务
        transaction.savepoint_commit(save_id)
    return {'retcode': 0}
